package cn.ailearn.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.InvalidKeyException;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

/**
 * 令牌工具类
 */

@Slf4j
public class JWTUtils {
    private static final String SECRET_KEY_STRING ="hBlN1j1A5Y5X1w1b8K9n6L3m2S4p7V0x2z5C8r1B3d6M9q4W7t0Y2u5H4j7K1l";//签名
    private static final long EXPIRATION_TIME=12*60*60*1000;//12小时
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(SECRET_KEY_STRING .getBytes(StandardCharsets.UTF_8));//密钥

    /**
     * 生成jwt令牌
     * @param claims 令牌中包含的信息
     * @return 生成的JWT令牌字符串
     */
    public static String createToken(Map<String ,Object> claims){
        try {
            long now = System.currentTimeMillis();
            Date issuedAt = new Date(now);
            // 创建JWT并进行签名及设置过期时间
            return Jwts.builder()
                    // 添加载荷信息
                    .claims(claims)
                    // 设置令牌签发时间
                    .issuedAt(issuedAt)
                    // 使用HS256算法和密钥进行签名
                    .signWith(SECRET_KEY)
                    // 设置令牌过期时间
                    .expiration(new Date(System.currentTimeMillis()+EXPIRATION_TIME))
                    // 生成紧凑的JWT字符串
                    .compact();
        } catch (InvalidKeyException e) {
            log.error("创建JWT令牌失败:{}",e.getMessage());
            throw new InvalidKeyException("JWT密钥无效");
        }
    }


    /**
     * 解析令牌
     * @param token 要解析JWT令牌字符串
     * @return 包含令牌信息的Claim对象
     * @throws Exception 如果令牌无效或已过期则抛出异常
     */
    public static Claims parseToken(String token){
        try {
            // 使用JWT工具类解析JWT字符串
            return Jwts.parser()
                    // 设置签名密钥，用于验证JWT的签名
                    .verifyWith(SECRET_KEY)
                    // 解析JWT字符串并验证签名及过期时间等，返回JWT的详细信息
                    .build()
                    .parseSignedClaims(token)
                    // 获取JWT的负载部分，其中包含用户信息等数据
                    .getBody();
        } catch (Exception e) {
            log.error("解析JWT令牌失败:{}",e.getMessage());
            throw e;
        }
    }
}
